package com.demo.oauth.config;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.common.DefaultThrowableAnalyzer;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.security.web.util.ThrowableAnalyzer;
import org.springframework.web.HttpRequestMethodNotSupportedException;

import com.demo.commons.results.CommonEnum;
import com.demo.oauth.exceptions.MyAuth2Exception;

import lombok.SneakyThrows;

/**
 * @author yangjian
 * @version 创建时间：2022年2月14日 下午2:10:14
 * 
 */
public class MyWebResponseExceptionTranslator implements WebResponseExceptionTranslator<OAuth2Exception> {

	private ThrowableAnalyzer throwableAnalyzer = new DefaultThrowableAnalyzer();

	@SneakyThrows
	@Override
	public ResponseEntity<OAuth2Exception> translate(Exception e) throws Exception {
		Throwable[] causeChain = throwableAnalyzer.determineCauseChain(e);

		Exception ase = (AuthenticationException) throwableAnalyzer
				.getFirstThrowableOfType(AuthenticationException.class, causeChain);
		if (ase != null) {
			return handleOAuth2Exception(CommonEnum.SERVER_ERROR);
		}

		ase = (AccessDeniedException) throwableAnalyzer.getFirstThrowableOfType(AccessDeniedException.class,
				causeChain);
		if (ase != null) {
			return handleOAuth2Exception(CommonEnum.SERVER_ERROR);
		}

		ase = (InvalidGrantException) throwableAnalyzer.getFirstThrowableOfType(InvalidGrantException.class,
				causeChain);
		if (ase != null) {
			String msg = ase.getMessage();
			if (msg.contains("Invalid refresh token")) {
				return handleOAuth2Exception(CommonEnum.REFRESH_TOKEN_ERROR);
			}
			return handleOAuth2Exception(CommonEnum.SERVER_ERROR);
		}

		// token 过期 特殊处理 返回 424 不是 401
		ase = (InvalidTokenException) throwableAnalyzer.getFirstThrowableOfType(InvalidTokenException.class,
				causeChain);
		if (ase != null) {
			return handleOAuth2Exception(CommonEnum.SERVER_ERROR);
		}

		ase = (HttpRequestMethodNotSupportedException) throwableAnalyzer
				.getFirstThrowableOfType(HttpRequestMethodNotSupportedException.class, causeChain);
		if (ase != null) {
			return handleOAuth2Exception(CommonEnum.SERVER_ERROR);
		}

		ase = (OAuth2Exception) throwableAnalyzer.getFirstThrowableOfType(OAuth2Exception.class, causeChain);

		if (ase != null) {
			return handleOAuth2Exception(CommonEnum.SERVER_ERROR);
		}
		return handleOAuth2Exception(CommonEnum.SERVER_ERROR);

	}

	private ResponseEntity<OAuth2Exception> handleOAuth2Exception(CommonEnum ce) {
		return new ResponseEntity<>(new MyAuth2Exception(ce.getMsg(), ce.getCode()), HttpStatus.OK);

	}

}
